package com.gitee.wsl.ext.string

import com.gitee.wsl.ext.base.isLineBreak


fun String.countOccurrences(char: Char, startIndex: Int = 0, ignoreCase: Boolean = false): Int {
    var count = 0
    var nextIndex = this.indexOfOrNull(char, startIndex, ignoreCase)

    while (nextIndex != null) {
        count++
        nextIndex = this.indexOfOrNull(char, nextIndex + 1, ignoreCase)
    }

    return count
}

fun String.countOccurrences(string: String, startIndex: Int = 0, ignoreCase: Boolean = false): Int {
    var count = 0
    var nextIndex = this.indexOfOrNull(string, startIndex, ignoreCase)

    while (nextIndex != null) {
        count++
        nextIndex = this.indexOfOrNull(string, nextIndex + 1, ignoreCase)
    }

    return count
}

fun String.lengthToEOF(start: Int = 0): Int {
    if (all { it.isLineBreak().not() }) return length - start
    var endIndex = start
    while (this.getOrNull(endIndex)?.isLineBreak()?.not() == true) {
        endIndex++
    }
    return endIndex - start
}

/**
 * Calculates the length of a String in UTF8 bytes in an optimized way
 * @throws IllegalArgumentException when string contains invalid UTF-16 surrogates or the UTF-8 length exceeds Int.MAX_VALUE
 */
fun String.calculateUTF8ByteLength(): Int {
    var utf8Length = 0
    var i = 0
    while (i < length) {
        val c = this[i]
        when {
            c.code < 0x80 -> utf8Length++
            c.code < 0x800 -> utf8Length += 2
            c.isHighSurrogate() -> {
                if (i + 1 >= length || !this[i + 1].isLowSurrogate()) {
                    throw IllegalArgumentException("Unpaired surrogate at index $i")
                }
                utf8Length += 4
                i++
            }
            c.isLowSurrogate() -> throw IllegalArgumentException("Unexpected low surrogate at index $i")
            else -> utf8Length += 3
        }
        i++
    }

    if (utf8Length < 0) {
        throw IllegalArgumentException("UTF-8 length overflow: ${utf8Length.toLong() and 0xFFFFFFFFL}")
    }
    return utf8Length
}